package com.hd.trans.ui.component

import android.content.Context
import android.media.AudioRecord
import android.os.Handler
import android.os.Looper
import android.text.TextUtils
import android.util.Log
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import com.hd.trans.common.Constants
import com.hd.trans.db.bean.HuDunLanguage
import com.hd.trans.network.PreferenceMgr
import com.hd.trans.ui.base.AppContextProvider
import com.hd.trans.ui.service.NetworkTaskService
import com.hd.trans.utils.NotificationUtil
import com.lyc.speechtranscriber.NuiSdkClient
import com.lyc.speechtranscriber.RecordingListener
import com.lyc.speechtranscriber.TranscriberAnalysisListener
import com.lyc.speechtranscriber.bean.HdAudioSource
import com.lyc.speechtranscriber.bean.MediaProjectionProvider
import kotlin.math.abs

class HdRecognitionComponent: RecognitionComponent, LifecycleObserver {

    private var mAudioSource: HdAudioSource = HdAudioSource.MIC
    private var mMediaProjectionProvider: MediaProjectionProvider? = null
    private var lastV: Float = 0f
    var isStop: Boolean = true
    private val mHandler: Handler = Handler(Looper.getMainLooper())
    private var isDestroy: Boolean = false
    private var aliKey: String? = null
    private var mRecognitionCallBack: RecognitionCallBack? = null//识别结果回调接口
    private var maxPauseTime = 800 //最大停顿时间，用于控制断句,默认800ms。有效范围：200-6000ms
    private var recordFileCallback: RecordFileCallback? = null//生成录音文件的回调接口
    private var isSplicing: Boolean = true
    private var context: Context = AppContextProvider.getContext()
    private val stringBuilder = StringBuilder()

    constructor(
        context: Context,
        isSplicing: Boolean = true,
        maxPauseTime: Int = 800,
        recordFileCallback: RecordFileCallback? = null,
    ){
        this.context = context
        this.isSplicing = isSplicing
        this.maxPauseTime = maxPauseTime
        this.recordFileCallback = recordFileCallback
        init()
    }

    constructor(
        context: Context,
        isSplicing: Boolean = true,
    ){
        this.context = context
        this.isSplicing = isSplicing
        init()
    }

    constructor(
        context: Context,
        isSplicing: Boolean = true,
        recordFileCallback: RecordFileCallback? = null,
    ){
        this.context = context
        this.isSplicing = isSplicing
        this.recordFileCallback = recordFileCallback
        init()
    }

    private fun init() {
        if (maxPauseTime < 200) {
            maxPauseTime = 200
        } else if (maxPauseTime > 6000) {
            maxPauseTime = 6000
        }
        NetworkTaskService.getInstance().start()
    }

    /**
     * 页面销毁 终止回调
     */
    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    fun destroy() {
        isDestroy = true
        mHandler.removeCallbacksAndMessages(null)
        stopRecognition()
    }

    override fun voiceRecognition(language: HuDunLanguage?, callBack: RecognitionCallBack?) {
        val aliKey = language?.aliAppKey
        voiceRecognition(aliKey, callBack)
    }

    fun voiceRecognition(aliKey: String?, callBack: RecognitionCallBack?) {
        stringBuilder.clear()
        this.aliKey = aliKey
        mRecognitionCallBack = callBack
        if (!aliKey.isNullOrEmpty()) {
            Log.w("语音识别", "阿里")
            if (TextUtils.isEmpty(PreferenceMgr.getInstance().translatePreference.aliToken)) {
                if (mRecognitionCallBack != null) {
                    mHandler.post(Runnable {
                        mRecognitionCallBack?.onRecognitionFailed(
                            "Empty Ali Token",
                            Constants.ResponseCode.ERROR_COMM
                        )
                    })
                }
                return
            }
            stopRecognition()
            mHandler.removeCallbacks(startAliRecognition)
            mHandler.postDelayed({
                //显示消息在通知栏
                NotificationUtil.getInstance().showMicrophoneNotification(startAliRecognition)
            }, 500)
        } else {
            if (mRecognitionCallBack != null) {
                mHandler.post(Runnable {
                    mRecognitionCallBack?.onRecognitionFailed(
                        "Empty Ali AppKey",
                        Constants.ResponseCode.ERROR_COMM
                    )
                })
                return
            }
        }
    }

    private val mRecordingListener by lazy {
        object : RecordingListener{
            override fun startRecording(id: String) {
                recordFileCallback?.createRecordFile(id)
            }

            override fun readBytes(bytes: ByteArray?) {
                recordFileCallback?.writeByteToFile(bytes)
            }

            override fun stopRecording(id: String) {
                NotificationUtil.getInstance().hideMicrophoneNotification()
                recordFileCallback?.savePcmToWav(id)
            }

        }
    }

    private val mTranscriberAnalysisListener by lazy {
        object : TranscriberAnalysisListener {
            override fun onEventTranscriberComplete() {
                //结束录制
                if (mRecognitionCallBack != null) {
                    mHandler.post(Runnable {
                        mRecognitionCallBack?.onRecognitionCompleted(
                            "",
                            0
                        )
                    })
                }
            }

            override fun onEventAsrPartialResult(result: String?) {
                //回调中间值
                if (mRecognitionCallBack != null) {
                    val content = if(isSplicing){
                        stringBuilder.toString() + result

                    }else{
                        result
                    }
                    mHandler.post(Runnable {
                        mRecognitionCallBack?.onRecognitionChanged(
                            content,
                            1,
                            false,
                            result
                        )
                    })
                }
            }

            override fun onEventSentenceEnd(result: String?) {
                //回调结果值
                if (mRecognitionCallBack != null) {
                    val content = if(isSplicing){
                        stringBuilder.append(result).toString()
                    }else{
                        result
                    }
                    mHandler.post(Runnable {
                        mRecognitionCallBack?.onRecognitionChanged(
                            content,
                            1,
                            true,
                            result
                        )
                    })
                }
            }

            override fun onEventAsrError(result: String?) {
                //错误反馈
                if (mRecognitionCallBack != null) {
                    mHandler.post(Runnable {
                        mRecognitionCallBack?.onRecognitionFailed(result, -1)
                    })
                }
            }

            override fun onEventDialogEx(result: String?) {
            }

            override fun onNuiAudioRMSChanged(v: Float) {
                mRecognitionCallBack?.onVoiceChanged(abs(v.toInt()), abs(lastV.toInt()))
                lastV = v
            }

        }
    }

    private val startAliRecognition = Runnable {
        val attribute = NuiSdkClient.getTranscriberAttribute()
            .setMaxSentenceSilence(maxPauseTime)
            .setMediaProjectionProvider(mMediaProjectionProvider)
            .setEnablePunctuation(aliKey != "oqj5iJOZgZoyLQyT")//维吾尔语不支持标点，开启会反馈乱码。

        NuiSdkClient.get().setRecordingListener(mRecordingListener)
        NuiSdkClient.get().setListener(mTranscriberAnalysisListener)
        NuiSdkClient.get().setAudioSource(mAudioSource)

        if(NuiSdkClient.get().createTranscriber(
                context,
                PreferenceMgr.getInstance().translatePreference.aliToken,
                requireNotNull(aliKey),
                attribute)){
            NuiSdkClient.get().start()
            isStop = false
        }

    }

    override fun stopRecognition() {
        isStop = true
        NuiSdkClient.get().stop()
        NuiSdkClient.get().release()
    }

    fun pauseRecording() {
        NuiSdkClient.get().stop()
    }

    fun resumeRecording() {
        NuiSdkClient.get().start()
    }

    fun isRecording(): Boolean {
        return NuiSdkClient.get().isRecording()
    }

    fun setAudioSource(audioSource: HdAudioSource) {
        mAudioSource = audioSource
        NuiSdkClient.get().setAudioSource(audioSource)
    }

    fun setMediaProjectionProvider(mediaProjectionProvider: MediaProjectionProvider?) {
        mMediaProjectionProvider = mediaProjectionProvider
    }

//    protected fun postHuDunEvent(eventCode: Int) {
//        postHuDunEvent(HuDunEvent<Any>(eventCode, getXClass()))
//    }
//
//
//    protected fun postHuDunEvent(eventCode: Int, data: Any) {
//        postHuDunEvent(HuDunEvent(eventCode, data, getXClass()))
//    }
//
//    private fun postHuDunEvent(event: HuDunEvent<*>?) {
//        if (null != event) {
//            EventBus.getDefault().post(event)
//        }
//    }
//
//    private fun getXClass(): Class<*>? {
//        return javaClass
//    }
}